home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint112s.zoo / xbios.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-15  |  9.8 KB  |  407 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * XBIOS replacement routines
  9.  */
  10.  
  11. #include "mint.h"
  12.  
  13. /* tty structures for the BIOS devices -- see biosfs.c */
  14. extern struct tty sccb_tty, scca_tty, ttmfp_tty;
  15. extern struct bios_tty bttys[];
  16. extern short btty_max;
  17.  
  18. extern int tosvers;    /* from main.c */
  19.  
  20. #define XBIOS_MAX 0x80
  21.  
  22. Func xbios_tab[XBIOS_MAX];    /* initially all zeros */
  23. short xbios_max = XBIOS_MAX;
  24.  
  25. /* NOTE: has_bconmap is initialized in main.c */
  26.  
  27. int has_bconmap;    /* flag: set if running under a version
  28.              * of TOS which supports Bconmap
  29.              */
  30. extern BCONMAP2_T *bconmap2;        /* bconmap struct */
  31. #define MAPTAB (bconmap2->maptab)
  32.  
  33. /*
  34.  * Supexec() presents a lot of problems for us: for example, the user
  35.  * may be calling the kernel, or may be changing interrupt vectors
  36.  * unexpectedly. So we play some dirty tricks here: the function
  37.  * call is treated like a signal handler, and we take advantage
  38.  * of the fact that no context switches will take place while
  39.  * in supervisor mode. ASSUMPTION: the user will not choose to
  40.  * switch back to user mode, or if s/he does it will be as part
  41.  * of a longjmp().
  42.  *
  43.  * BUG: if the user function switches to user mode, then back to
  44.  * supervisor mode and returns, then the returned value may be
  45.  * inaccurate (this happens if two programs make Supexec calls
  46.  * at the same time).
  47.  */
  48.  
  49. long ARGS_ON_STACK (*usrcall) P_((long, long,long,long,long,long));
  50. long usrret;
  51. long usrarg1, usrarg2, usrarg3, usrarg4, usrarg5;
  52.  
  53. #if 0
  54. /* moved to syscall.spp */
  55. static void ARGS_ON_STACK do_usrcall P_((void));
  56.  
  57. static void ARGS_ON_STACK
  58. do_usrcall()
  59. {
  60.     usrret = (*usrcall)((long)usrcall, usrarg1, usrarg2, usrarg3, usrarg4,
  61.          usrarg5);
  62. }
  63. #endif
  64.  
  65. long ARGS_ON_STACK
  66. supexec(funcptr, arg1, arg2, arg3, arg4, arg5)
  67.     Func funcptr;
  68.     long arg1, arg2, arg3, arg4, arg5;
  69. {
  70.     short savesr;
  71.     CONTEXT *syscall = &curproc->ctxt[SYSCALL];
  72.  
  73. /* set things up so that "signal 0" will be handled by calling the user's
  74.  * function.
  75.  */
  76.  
  77.     usrcall = funcptr;
  78.     usrarg1 = arg1;
  79.     usrarg2 = arg2;
  80.     usrarg3 = arg3;
  81.     usrarg4 = arg4;
  82.     usrarg5 = arg5;
  83.     curproc->sighandle[0] = (long)do_usrcall;
  84.     savesr = syscall->sr;    /* save old super/user mode flag */
  85.     syscall->sr |= 0x2000;    /* set supervisor mode */
  86.     handle_sig(0);        /* actually call out to the user function */
  87.     syscall->sr = savesr;
  88.  
  89. /* do_usrcall saves the user's return value in usrret */
  90.     return usrret;
  91. }
  92.  
  93.  
  94. /*
  95.  * midiws: we have to replace this, because it's possible that the process'
  96.  * view of what the MIDI port is has been changed by Fforce or Fmidipipe
  97.  */
  98.  
  99. long ARGS_ON_STACK
  100. midiws(cnt, buf)
  101.     int cnt;
  102.     const char *buf;
  103. {
  104.     FILEPTR *f;
  105.     long towrite = cnt+1;
  106.  
  107.     f = curproc->handle[-5];    /* MIDI output handle */
  108.     if (!f) return EIHNDL;
  109.  
  110.     if (is_terminal(f)) {
  111.         extern FILESYS bios_filesys;
  112.  
  113.         /* see if we can do fast RAW byte IO thru the device driver... */
  114.         if ((f->fc.fs != &bios_filesys ||
  115.             (towrite > 1 &&
  116.              ((struct bios_file *)f->fc.index)->drvsize >
  117.                 offsetof (DEVDRV, writeb))) && f->dev->writeb) {
  118.             struct tty *tty = (struct tty *)f->devinfo;
  119.  
  120.             tty_checkttou (f, tty);
  121.             tty->state &= ~TS_COOKED;
  122.             if ((towrite = (*f->dev->writeb)(f, buf, towrite)) != EUNDEV)
  123.                 return towrite;
  124.         }
  125.         while (cnt >= 0) {
  126.             tty_putchar(f, (long)*buf, RAW);
  127.             buf++; cnt--;
  128.         }
  129.         return towrite;
  130.     }
  131.     return (*f->dev->write)(f, buf, towrite);
  132. }
  133.  
  134. /*
  135.  * Modem control things: these are replaced because we handle
  136.  * Bconmap ourselves
  137.  */
  138.  
  139. /* mapin: utility routine, does a Bconmap and keeps track
  140.  * so we call the kernel only when necessary; call this
  141.  * only if has_bconmap is "true".
  142.  * Returns: 0 on failure, 1 on success.
  143.  */
  144. int curbconmap;
  145.  
  146. int
  147. mapin(dev)
  148.     int dev;
  149. {
  150.     long r;
  151.  
  152.     if (dev == curbconmap)
  153.         return 1;
  154.     r = Bconmap(dev);
  155.     if (r) {
  156.         curbconmap = dev;
  157.         return 1;
  158.     }
  159.     return 0;
  160. }
  161.     
  162. long ARGS_ON_STACK
  163. uiorec(dev)
  164.     int dev;
  165. {
  166.     TRACE(("Iorec(%d)", dev));
  167.     if (dev == 0 && has_bconmap) {
  168. /* get around another BIOS Bug:  in (at least) TOS 2.05 Iorec(0) is broken */
  169.         if ((unsigned)curproc->bconmap-6 < btty_max)
  170.             return (long)MAPTAB[curproc->bconmap-6].iorec;
  171.         mapin(curproc->bconmap);
  172.     }
  173.     return (long)Iorec(dev);
  174. }
  175.  
  176. long ARGS_ON_STACK
  177. rsconf(baud, flow, uc, rs, ts, sc)
  178.     int baud, flow, uc, rs, ts, sc;
  179. {
  180.     long rsval;
  181.     static int oldbaud = -1;
  182.     unsigned b = 0;
  183.     struct bios_tty *t = bttys;
  184.  
  185.     TRACE(("Rsconf(%d,%d,%d,%d,%d,%d)", baud, flow,
  186.         uc, rs, ts, sc));
  187.  
  188.     if (has_bconmap) {
  189.         b = curproc->bconmap-6;
  190.         if (b < btty_max)
  191.             t += b;
  192.         else
  193.             t = 0;
  194. /* more bugs...  serial1 is three-wire, requesting hardware flowcontrol
  195.  * on it can confuse BIOS
  196.  */
  197.         if ((flow & 0x8002) == 2 && t && t->tty == &ttmfp_tty)
  198.             flow &= ~2;
  199.  
  200. #ifndef DONT_ONLY030_THIS
  201. /* Note: the code below must be included, even on a 68030, thanks to a bug
  202.  * in the gcc and mntlib osbind.h file.
  203.  */
  204.  
  205. /*
  206.   If this is an old TOS, try to rearrange things to support
  207.   the following Rsconf() features:
  208.     1. Rsconf(-2, ...) does not return current baud (it crashes)
  209.         -> keep track of old speed in static variable
  210.     2. Rsconf(b, ...) sends ASCII DEL to the modem unless b == -1
  211.         -> make speed parameter -1 if new speed matches old speed
  212.     3. Rsconf() discards any buffered output
  213.         -> use Iorec() to ensure all buffered data was sent before call
  214. */
  215.     } else if (tosvers < 0x0104) {
  216.         if (baud == -2) {
  217. /* 1.(0)4 Rsconf ignores its other args when asked for old speed, so can we */
  218.             return oldbaud;
  219.         } else if (baud == oldbaud)
  220.             baud = -1;
  221.         else if (baud > -1)
  222.             oldbaud = baud;
  223.     }
  224.     if (t && baud != -2) {
  225.         while (t->tty->hup_ospeed) {
  226.             sleep (IO_Q, (long)&t->tty->state);
  227.         }
  228.     }
  229. #if 0 /* now handled in tty.c (real TIOCSETP) */
  230. /* This part _is_ necessary on TOS 1.04 */
  231.     if (tosvers <= 0x0104) {
  232.         int attempts = 0;
  233.         short old_head;
  234.         IOREC_T *ior= ((IOREC_T *) uiorec(0)) + 1; /* output record */
  235.         old_head = ior->head;
  236.         while (ior->head != ior->tail) {
  237.             if (++attempts >= 50) { /* prevent getting stuck by flow control */
  238.                 if (old_head == ior->head)
  239.                     break;
  240.                 else {
  241.                     old_head = ior->head;
  242.                     attempts = 0;
  243.                 }
  244.             }
  245.             TRACE(("Rsconf() napping until transmit buf empty"));
  246.             nap(200);
  247.         }
  248.     }
  249. #endif
  250. #endif /* ONLY030 */
  251.  
  252.     if (has_bconmap && t) {
  253.         rsval = MAPTAB[b].rsconf;
  254. /* bug # x+1:  at least up to TOS 2.05 SCC Rsconf forgets to or #0x700,sr...
  255.  * use MAPTAB to call it directly, at ipl7 if it points to ROM
  256.  */
  257.         if (baud > -2 &&
  258.             (b == 1 || t->tty == &scca_tty) &&
  259.             (b = 1, rsval > 0xe00000L) && rsval < 0xefffffL)
  260.             rsval = callout6spl7 (rsval, baud, flow, uc, rs, ts, sc);
  261.         else
  262.             rsval = callout6 (rsval, baud, flow, uc, rs, ts, sc);
  263.     } else {
  264.         if (has_bconmap)
  265.             mapin(curproc->bconmap);
  266.         rsval = Rsconf(baud, flow, uc, rs, ts, sc);
  267.     }
  268.     if (!t || baud <= -2)
  269.         return rsval;
  270.  
  271.     if (baud >= 0) {
  272.         t->vticks = 0;
  273.         t->ospeed = t->ispeed = (unsigned)baud < t->maxbaud ?
  274.                     t->baudmap[baud] : -1;
  275.     }
  276. #if 1
  277.     if (b == 1 && flow >= 0) {
  278. /*
  279.  * SCC can observe CD and CTS in hardware (w3 bit 5), turn on if
  280.  * TF_CAR and T_RTSCTS
  281.  */
  282.         short sr;
  283.         volatile char dummy, *control;
  284.         unsigned char w3;
  285.  
  286.         control = (volatile char *)
  287.             (t->tty == &scca_tty ? 0xffff8c81L : 0xffff8c85L);
  288.         w3 = ((((unsigned char *) t->irec)[0x1d] << 1) & 0xc0) |
  289.             ((!t->clocal &&
  290.              (((unsigned char *) t->irec)[0x20] & 2)) ? 0x21 : 0x1);
  291.         sr = spl7();
  292.         dummy = *((volatile char *) 0xfffffa01L);
  293.         *control = 3;
  294.         dummy = *((volatile char *) 0xfffffa01L);
  295.         *control = w3;
  296.         spl(sr);
  297.     }
  298. #endif
  299.     return rsval;
  300. }
  301.  
  302. long ARGS_ON_STACK
  303. bconmap(dev)
  304.     int dev;
  305. {
  306.     int old = curproc->bconmap;
  307.  
  308.     TRACE(("Bconmap(%d)", dev));
  309.  
  310.     if (has_bconmap) {
  311.         if (dev == -1) return old;
  312.         if (dev == -2) return Bconmap(-2);
  313.         if (dev == 0) return 0;  /* the user's just testing */
  314.         if (mapin(dev) == 0) {
  315.             DEBUG(("Bconmap: mapin(%d) failed", dev));
  316.             return 0;
  317.         }
  318.         if (set_auxhandle(curproc, dev) == 0) {
  319.             DEBUG(("Bconmap: Couldn't change AUX:"));
  320.             return 0;
  321.         }
  322.         curproc->bconmap = dev;
  323.         return old;
  324.     }
  325.     return EINVFN;    /* no Bconmap available */
  326. }
  327.  
  328. /*
  329.  * cursconf(): this gets converted into an ioctl() call on
  330.  * the appropriate device
  331.  */
  332.  
  333. long ARGS_ON_STACK
  334. cursconf(cmd, op)
  335.     int cmd, op;
  336. {
  337.     FILEPTR *f;
  338.  
  339.     f = curproc->handle[-1];
  340.     if (!f || !is_terminal(f))
  341.         return EINVFN;
  342.     return
  343.       (*f->dev->ioctl)(f, TCURSOFF+cmd, &op);
  344. }
  345.  
  346.  
  347. long ARGS_ON_STACK
  348. dosound(ptr)
  349.     const char *ptr;
  350. {
  351.     MEMREGION *r;
  352.  
  353.     if (!no_mem_prot && ((long)ptr >= 0)) {
  354.     /* check that this process has access to the memory */
  355.     /* (if not, the next line will cause a bus error) */
  356. #ifdef __TURBOC__
  357.     /* work-around for buggy optimizer */
  358.         char dummy = (*((volatile char *)ptr));
  359.         UNUSED(dummy);
  360. #else
  361.         (void)(*((volatile char *)ptr));
  362. #endif
  363.     /* OK, now make sure that interrupt routines will have access,
  364.      * too
  365.      */
  366.         r = addr2region((long)ptr);
  367.         if (r && get_prot_mode(r) == PROT_P) {
  368.             DEBUG(("Dosound: changing protection to Super"));
  369.             mark_region(r, PROT_S);
  370.         }
  371.     }
  372.  
  373.     return call_dosound(ptr);
  374. }
  375.  
  376. void
  377. init_xbios()
  378. {
  379.     int i, oldmap;
  380.  
  381.     curbconmap = (has_bconmap) ? (int) Bconmap(-1) : 1;
  382.  
  383.     xbios_tab[0x0c] = midiws;
  384.     xbios_tab[0x0e] = uiorec;
  385.     xbios_tab[0x0f] = rsconf;
  386.     xbios_tab[0x15] = cursconf;
  387.     xbios_tab[0x20] = dosound;
  388.     xbios_tab[0x26] = supexec;
  389.     xbios_tab[0x2c] = bconmap;
  390.  
  391.     oldmap = curproc->bconmap = curbconmap;
  392.     for (i=0; i<btty_max; i++) {
  393.         int r;
  394.         if (has_bconmap)
  395.             curproc->bconmap = i+6;
  396.         r = (int)rsconf(-2, -1, -1, -1, -1, -1);
  397.         if (r < 0) {
  398.             if (has_bconmap)
  399.                 mapin (curproc->bconmap);
  400.             Rsconf((r=0), -1, -1, -1, -1, -1);
  401.         }
  402.         rsconf(r, -1, -1, -1, -1, -1);
  403.     }
  404.     if (has_bconmap)
  405.         mapin (curproc->bconmap = oldmap);
  406. }
  407.